import React, { useEffect, useRef, useState } from 'react';
import { List, Spin, Button, message } from 'antd';
import axios from 'axios';

// 使用长轮询（Long Polling）监听订单状态变更，服务端有更新时立即返回数据，无更新则保持连接 30 秒。
const OrderStatusPolling = () => {
  const [isPolling, setIsPolling] = useState(false);
  const [orderStatus, setOrderStatus] = useState('等待支付');
  const [isLoading, setIsLoading] = useState(false);
  const isPollingRef = useRef(isPolling); // 用 ref 存储 isPolling 最新值

  // 长轮询核心逻辑
  const pollForUpdates = () => {
    setIsLoading(true);
    axios.get('https://api.virapi.com/little7plum585/usual-mock-data/order_status', {
      timeout: 30000 // 长轮询超时时间
    })
    .then(response => {
      setOrderStatus(response.data.data.status);
      message.info(`订单状态更新：${response.data.data.status}`);
      if (isPollingRef.current) pollForUpdates(); // 递归调用实现持续轮询
    })
    .catch(error => {
      if (isPollingRef.current && error.code === 'ECONNABORTED') {
        // 超时后重新请求
        pollForUpdates();
      } else {
        message.error('获取订单状态失败');
      }
    })
    .finally(() => setIsLoading(false));
  };

  // 监听 isPolling 变化，更新 ref
  useEffect(() => {
    isPollingRef.current = isPolling;
  }, [isPolling]);

  // 启动/停止轮询
  const togglePolling = () => {
    setIsPolling(prev => {
      const nextState = !prev;
      nextState &&pollForUpdates(); // 首次调用触发长轮询
      return nextState;
    });
  };

  return (
    <div style={{ padding: 20 }}>
      <h2>订单状态追踪</h2>
      <Button type="primary" onClick={togglePolling}>
        {isPolling ? '停止监听' : '开始追踪订单'}
      </Button>
      {isLoading && <Spin style={{ marginLeft: 16 }} />}

      <List
        style={{ marginTop: 24 }}
        bordered
        dataSource={[orderStatus]}
        renderItem={(status) => {
          return(
            <List.Item>
              当前状态：<strong>{status}</strong>
            </List.Item>
          )
        }}
      />
    </div>
  );
};

export default OrderStatusPolling;

// 一、问题根源：闭包中的状态未更新
// 状态更新机制：
// setIsPolling是异步更新状态的，togglePolling中设置nextState为true后，组件会重新渲染，但闭包中的isPolling仍然是旧值（初始为false）。
// 在pollForUpdates中，if (isPolling)判断的是函数创建时的isPolling值（闭包特性），而非最新状态。
// 代码执行流程：
// 点击 “开始追踪订单” → togglePolling触发，isPolling设为true（组件未立即重新渲染）。
// 首次调用pollForUpdates，此时闭包中的isPolling为旧值false，导致递归条件不成立，长轮询中断。
// 二、解决方案：使用函数参数或useRef获取最新状态

